package com.ts.api.module.match.plan.internal.distribute.strategy;

import com.gitee.apanlh.util.base.BigDecimalUtils;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.module.api.convert.core.handler.ApiConvertHandler;
import com.ts.api.module.api.convert.core.http.client.ApiHttpMessage;
import com.ts.api.module.api.convert.plan.http.ApiPlanHttpHandler;
import com.ts.api.module.api.convert.platform.entity.RespPlatformMultiPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMd5DataExchange;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistribute;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeField;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributePost;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeResult;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeUserRequest;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 *  基础前置分发校验
 *
 *  @author Pan
 */
@Service
public class BaseDistribute implements PlanDistributeStrategy {

    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ApiPlanHttpHandler apiPlanHttpHandler;

    @Override
    public PlanDistributeResult preValidate(PlanDistribute planDistribute) {
        ProductPlanPO productPlanPO = planDistribute.getProductPlanPO();
        ProductApplyFlowPO currentFlow = planDistribute.getCurrentDistributeFlow();

        //  获取请求用户参数
        PlanDistributeUserRequest planDistributeUserRequest = planDistribute.getPlanDistributeUserRequest();
        Long loanChannelId = planDistributeUserRequest.getLoanChannelId();

        //  判断是否渠道被屏蔽
        boolean hasChannelFilter = apiBizRequiredService.hasChannelFilter(currentFlow, productPlanPO, loanChannelId, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
        if (hasChannelFilter) {
            return PlanDistributeResult.ofFail(planDistribute, "该计划已屏蔽该渠道");
        }

        //  判断计划限量
        boolean hasLimitTotal = apiBizRequiredService.hasLimitTotal(currentFlow, productPlanPO, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
        if (hasLimitTotal) {
            return PlanDistributeResult.ofFail(planDistribute, "该计划限量");
        }

        //  验证主体余额是否足够本次扣款
        boolean requiredProductAmount = apiBizRequiredService.requiredProductAmount(currentFlow, productPlanPO, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
        if (!requiredProductAmount) {
            return PlanDistributeResult.ofFail(planDistribute, "主体余额不足");
        }
        return PlanDistributeResult.ofEmptySuc();
    }

    @Override
    public PlanDistributeResult distribute(PlanDistribute planDistribute) {
        ProductApplyFlowPO currentDistributeFlow = planDistribute.getCurrentDistributeFlow();

        //  撞库分发
        ApiHttpMessage httpMessage = apiPlanHttpHandler.sendDataExchange(planDistribute);

        boolean hasRespTimeout = apiBizRequiredService.hasHttpTimeOut(currentDistributeFlow, httpMessage, ProductApplyFlowStatusEnum.DATA_EXCHANGE_REQ_TIMEOUT);
        if (hasRespTimeout) {
            PlanDistributeResult planDistributeResult = PlanDistributeResult.ofFail(planDistribute);
            planDistributeResult.setApiHttpMessage(httpMessage);
            planDistributeResult.setBizErrorMsg("HTTP超时/或连接不通");
            return planDistributeResult;
        }

        boolean hasHttpExp = apiBizRequiredService.hasHttpExp(currentDistributeFlow, httpMessage, true, ProductApplyFlowStatusEnum.DATA_EXCHANGE_EXCEPTION);
        if (hasHttpExp) {
            PlanDistributeResult planDistributeResult = PlanDistributeResult.ofFail(planDistribute);
            planDistributeResult.setApiHttpMessage(httpMessage);
            planDistributeResult.setBizErrorMsg("HTTP异常");
            return planDistributeResult;
        }

        //  构建成功对象
        return PlanDistributeResult.ofEmptySuc(planDistribute, httpMessage);
    }

    @Override
    public PlanDistributeField parseResponse(PlanDistribute planDistribute, ApiHttpMessage httpMessage, ApiConvertHandler handler) {
        throw new AbstractMethodError("parseResponse基础类未实现该方法");
    }

    @Override
    public PlanDistributeResult post(PlanDistributePost planDistributePost) {
        throw new AbstractMethodError("post基础类未实现该方法");
    }

    /**
     *  验证是否存在MD5库排重
     *
     *  @param  planDistribute     分发对象
     *  @return boolean
     */
    boolean validExistMd5Filter(PlanDistribute planDistribute) {
        PlanDistributeUserRequest planDistributeUserRequest = planDistribute.getPlanDistributeUserRequest();
        ProductApplyFlowPO currentDistributeFlow = planDistribute.getCurrentDistributeFlow();
        ProductPlanPO productPlanPO = planDistribute.getProductPlanPO();

        String phoneMd5 = planDistributeUserRequest.getPhoneMd5();
        boolean hasExistMd5Filter = apiBizRequiredService.hasExistMd5Filter(currentDistributeFlow, productPlanPO, phoneMd5, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
        if (hasExistMd5Filter) {
            return false;
        }
        return true;
    }

    /**
     *  解析返回对象-并且验证是否空字段
     *
     *  @param  respData                 响应实体
     *  @param  hasPlatShare             是否平台分润模式
     *  @return boolean
     */
    String validRespPlatformByMd5(RespPlatformPhoneMd5DataExchange respData, boolean hasPlatShare) {
        String errorMsg = null;

        //  返回单价
        BigDecimal price = respData.getPrice();

        if (ValidParam.isEmpty(respData.getDisplayName())) {
            errorMsg = "业务失败, 返回【投放名称】为空";
            return errorMsg;
        }
        if (ValidParam.isEmpty(respData.getProductName())) {
            errorMsg = "业务失败, 返回【产品名称】为空";
            return errorMsg;
        }
        //  分润模式必传价格， 单价模式忽略
        if (hasPlatShare) {
            if (ValidParam.isNull(price)) {
                errorMsg = "业务失败, 返回【价格】为空";
                return errorMsg;
            } else if (BigDecimalUtils.compare(price, 0) <= 0) {
                errorMsg = "业务失败, 返回【价格】非法";
                return errorMsg;
            }
        }

        return errorMsg;
    }

    /**
     *  解析返回对象-并且验证是否空字段
     *
     *  @param  respData                 响应实体
     *  @param  hasPlatShare             是否平台分润模式
     *  @param  hasPlatOtherProvider     是否对方接入文档
     *  @return boolean
     */
    String validRespPlatformByPhoneMask(RespPlatformMultiPhoneMaskDataExchange respData, boolean hasPlatShare, boolean hasPlatOtherProvider) {
        String errorMsg = null;

        List<RespPlatformPhoneMaskDataExchange> listPhoneMask = respData.getListPhoneMask();
        //  过滤为null的对象
        CollUtils.filter(listPhoneMask, t -> t == null);

        //  空对象返回
        if (ValidParam.isEmpty(listPhoneMask)) {
            errorMsg = "业务失败, 无返回对象";
            return errorMsg;
        }

        for (int i = 0; i < listPhoneMask.size(); i++) {
            RespPlatformPhoneMaskDataExchange respItem = listPhoneMask.get(i);
            if (ValidParam.isEmpty(respItem.getDisplayName())) {
                errorMsg = "业务失败, 返回【投放名称】为空";
                break;
            }
            if (ValidParam.isEmpty(respItem.getProductName())) {
                errorMsg = "业务失败, 返回【产品名称】为空";
                break;
            }
            if (hasPlatOtherProvider && ValidParam.isEmpty(respItem.getApplyId())) {
                errorMsg = "业务失败, 返回【订单号】为空";
                break;
            }

            //  返回单价
            BigDecimal price = respItem.getPrice();
            //  分润模式必传价格， 单价模式忽略
            if (hasPlatShare) {
                if (ValidParam.isNull(price)) {
                    errorMsg = "业务失败, 返回【价格】为空";
                    break;
                } else if (BigDecimalUtils.compare(price, 0) <= 0) {
                    errorMsg = "业务失败, 返回【价格】非法";
                    break;
                }
            }
        }
        return errorMsg;
    }
}
